package xj.graph2d;

import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.io.Serializable;
import java.util.List;
import java.util.ListIterator;
import java.util.Set;

import xj.lang.CodeWriter;
import xj.meta.ModelElement;

public interface DrawShape 
  extends Serializable, Cloneable {

  // Cloning
  public Object clone()
    throws CloneNotSupportedException;
  public DrawShape cloneDrawShape(boolean deepClone)
    throws CloneNotSupportedException;

  // Structure
  public DrawShape getParent();

  public void setParent(DrawShape c);

  public DrawShape getTopShape();

  public List<DrawShape> getShapes();

  public int addShape(DrawShape s);

  public int addShape(DrawShape s, boolean select);

  public void addShapes(List<DrawShape> list);

  public void insertShapeAt(DrawShape s, int i);

  public void insertShapeAt(DrawShape s, int i, boolean select);

  /**
   * Return the index of s
   */
  public int insertShapeAtTop(DrawShape s, boolean select);

  public void insertShapeAtBottom(DrawShape s, boolean select);

  public boolean removeShape(DrawShape s);

  public DrawShape removeShape(int i);

  public void removeAllShapes();

  public int getShapeCount();

  public DrawShape getShape(int i);

  public int indexOfShape(DrawShape s);

  public DrawShape findInRole(int role);

  public DrawShape findInRole(String rolename);

  public List<DrawShape> findAllInRole(int role);

  public List<DrawShape> findAllInRole(String rolename);

  public ListIterator<DrawShape> allShapes();

  public boolean isClipSubShapes();

  public void setClipSubShapes(boolean b);

  public boolean isSubShapeClipped(DrawShape subshape);

  // Is this a descendant of shape s?
  public boolean isDescendantOf(DrawShape s);

  // Attributes
  public boolean isFilled();

  public void setFilled(boolean filled);

  public boolean isShadow();

  public void setShadow(boolean shadow);

  public int getShadowWidth();

  public void setShadow(boolean shadow, int shadowWidth);

  public void setShadow(boolean shadow, boolean recurse);

  public boolean isFixedRatio();

  public void setFixedRatio(boolean fixedRatio);

  public boolean isBlured();

  public void setBlured(boolean blured);

  public boolean isEditable();

  public void setEditable(boolean e);

  public boolean isAllowRotation();

  public void setAllowRotation(boolean allowRotation);

  public Point2D getRotationAnchor();

  public boolean isSymetricResize();

  public void setSymetricResize(boolean symetricResize);

  public boolean isVisible();

  public void setVisible(boolean v);

  public boolean isAtomic();

  public void setAtomic(boolean a);

  public boolean isDetachable();

  public void setDetachable(boolean s);

  public boolean isCompound();

  public boolean isEdgeSensitive();

  public boolean isCornorSensitive();

  public boolean isMovable();

  public void setMovable(boolean s);

  public boolean isScalable();

  public void setScalable(boolean s);

  public int getScaleMode();

  public void setScaleMode(int scaleMode);

  public boolean isResizable();

  public void setResizable(boolean s);

  public boolean isSearchable();

  public void setSearchable(boolean s);

  public boolean isSelectable();

  public void setSelectable(boolean s);

  public boolean isAcceptSubshape();

  public boolean isAcceptSubshape(DrawShape subshape);

  public void setAcceptSubshape(boolean acceptSubshape);

  public boolean isSticky();

  public void setSticky(boolean s);

  public boolean isFitted();

  public void setFitted(boolean f);

  /*
   * The distance of movement allowed in X and Y direction. dx, dy are the
   * distance attempted to move. The return value is the allowed distance in
   * the same direction of dx/dy 
   * |return value| <= |dx or dy|
   */
  public float canMoveX(float dx);

  public float canMoveY(float dy);

  /* 
   * To ensure the convention/invariant of a shape holds after modification.  
   * Does not change the dimension of the shape.
   */
  public void normalize();

  public Rectangle2D getBounds();

  public Rectangle2D getFrameBounds();

  public Rectangle2D getRepaintRect();

  public DrawAttr getDrawAttr();

  public DrawAttr getThisDrawAttr();

  public void setDrawAttr(DrawAttr attr);

  public int getCursor();

  public Point2D getCursorPosition();

  public DrawShape findLeftMostShape();

  public DrawShape findRightMostShape();

  public DrawShape setCursorLeftEnd();

  public DrawShape setCursorRightEnd();

  public DrawShape setCursor(int i);

  public DrawShape setCursor(Point2D p);

  /* move cursor to the next subshape */
  public void incCursor();

  /* move cursor to the previous subshape */
  public void decCursor();

  public void showBorder(boolean b);

  public boolean isShowBorder();

  public void showCursor(boolean b);

  public boolean isCloneLabel();

  public void setCloneLabel(boolean cloneLabel);

  public boolean isLabel(DrawShape shape);

  public DrawShape getSelectedSubShape();

  public void setSelectedSubShape(DrawShape s);

  public DrawShape findSubshape(Predicate pred);

  public DrawShape findSubshape(Predicate pred, boolean recurse);

  public List<DrawShape> findAllSubshapes(Predicate pred);

  public List<DrawShape> findAllSubshapes(Predicate pred, boolean recurse);

  public List<DrawShape> findAllSubshapes(Predicate pred, boolean recurse, 
					  List<DrawShape> result);

  public DrawShapeSearch.Result searchSubShapes(Point2D p);

  public DrawShapeSearch.Result searchSubShapes(Point2D p, DrawShape exclude);

  public DrawShapeSearch.Result searchSubShapes(Point2D p, DrawShape exclude, 
						boolean excludeOpenShape);

  public int isInside(Point2D p);

  public int isInside(float px, float py);

  public boolean isOutside(Point2D p);

  public boolean isOutside(float px, float py);

  public int isOnHotSpot(Point2D p);

  public int isOnHotSpot(float px, float py);

  public void drawShape(Graphics2D g2);

  public void drawShape(Graphics2D g2, int mode);

  public void drawShape(Graphics2D g2, DrawShape selectedShape);

  public void drawShape(Graphics2D g2, DrawShape selectedShape,
			Set<DrawShape> selectionSet);

  public void drawShape(Graphics2D g2, int mode, 
			DrawShape selectedShape);

  public void drawShape(Graphics2D g2, int mode, 
			DrawShape selectedShape,
			Set<DrawShape> selectionSet);

  public void draw(Graphics2D g2);

  public void drawCursor(Graphics2D g2);

  public void drawOutline(Graphics2D g2, float x1, float y1, float x2, float y2);

  public void drawOutline(Graphics2D g2);

  public void drawFrame(Graphics2D g2);

  public void drawSubShapesOutline(Graphics2D g2);

  public void drawSubShapes(Graphics2D g2, int mode, 
			    DrawShape selectedShape,
			    Set<DrawShape> selectionSet);

  public void drawSubShapes(Graphics2D g2, int mode, 
			    DrawShape selectedShape,
			    Set<DrawShape> selectionSet,
			    boolean reverseOrder);

  public Rectangle2D getBoundingRect();

  public Shape getOutlineShape();

  public void adjustBounds();

  public void setBounds(float x1, float y1, float x2, float y2);

  public void setEnds(Point2D p1, Point2D p2);

  public void setPosition(Point2D p);

  public void setPosition(float x, float y);

  public Point2D getPosition();

  public void setCenterPosition(Point2D p);

  public void setCenterPosition(float x, float y);

  public boolean isZeroSize();

  public Point2D getEnd1();

  public Point2D getEnd2();

  public Point2D getCenterPosition();

  public float getShapeWidth();

  public float getShapeHeight();

  public void move(float dx, float dy);

  public void moveNotify(float dx, float dy);

  public void setEnds(float x1, float y1, float x2, float y2);

  public void setEndsAdj(float x1, float y1, float x2, float y2);

  public void scale(float sx, float sy);

  public void scaleEnds(float x1, float y1, float x2, float y2);

  public void setEnd1(float dx, float dy);

  public void setEnd2(float dx, float dy);

  public void moveEnd1(float dx, float dy);

  public void moveEnd2(float dx, float dy);

  public void moveCorner(int pos, float dx, float dy);

  public void moveCorner(int pos, float dx, float dy, boolean scaleSubshapes);

  public void moveEdge(int pos, float dx, float dy);

  public void moveEdge(int pos, float dx, float dy, boolean scaleSubshapes);

  public void moveCircumference(float px, float py);

  public void recalculateBounds();

  public void calculateBounds();

  public AffineTransform getTransform();

  public void setToRotation(float vx, float vy);

  public float getRotationAngle();

  public void setRotationAngle(float angle);

  public void writeXML(CodeWriter out, int mode, String namespacePrefix);

  public void setAttrFromXML(org.w3c.dom.Element node, String namespaceURI);

  public String getName();

  public void setName(String name);

  public String getTemplateName();

  public void setTemplateName(String name);

  public String getDisplayName();

  public void setDisplayName(String tname);

  public String getAnnotation();

  public void setAnnotation(String annotation);

  public int getRole();

  public void setRole(int role);

  public int getFlag();

  public void setFlag(int flag);

  public int getDeco();

  public void setDeco(int deco);

  public String getRoleName();

  public void setRoleName(String name);

  public DrawShapeMessage getMessage();

  public void setMessage(DrawShapeMessage message);

  public int getDisplayMode();

  public void setDisplayMode(int displayMode);

  public ModelElement getModel();

  public void setModel(ModelElement model);

  public Object getCustomAttribute(String key);

  public void setCustomAttribute(String key, Object value);

  public ModelListener getModelListener();

  public void setModelListener(ModelListener ml);

  /*
   * Update the model associated with this shape based on the visual representation of this shape  
   */
  public void updateModel();

  /*
   * Update the visual representation of this shape based on the model associated with this shape 
   */
  public void updateShape();

  public String getBoundsString();

  /*
   * Does not change the dimension of the shape
   */
  public void doLayout();

  /*
   * Does not change the dimension of the shape.
   * May move and layout subshapes, all subshapes retain dimension  
   */
  public void layoutComponents();

  /*
   * May change the dimension of the shape, result in a shape fitted to the subshapes. 
   * May move and fit descedent shapes.    
   */
  public void fitComponents();

  public void adjustParentLayout();

  /*
   * Notify that a subshape comp has been moved. 
   * Used for subshapes that are fixed to the parent, the parent should move the same amount  
   */
  public void componentMoved(DrawShape comp, float dx, float dy);

  /*
   * Notify that the dimension of a subshape comp has been changed. 
   * Used for notifying the parent to adjust its dimension if necessary
   */
  public void componentDimensionChanged(DrawShape comp);
  
}
